home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 25 / AACD 25.iso / AACD / Utilities / BasiliskII / src / BeOS / extfs_beos.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-03-31  |  10.5 KB  |  461 lines

  1. /*
  2.  *  extfs_beos.cpp - MacOS file system for access native file system access, BeOS specific stuff
  3.  *
  4.  *  Basilisk II (C) 1997-2001 Christian Bauer
  5.  *
  6.  *  This program is free software; you can redistribute it and/or modify
  7.  *  it under the terms of the GNU General Public License as published by
  8.  *  the Free Software Foundation; either version 2 of the License, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  */
  20.  
  21. #include "sysdeps.h"
  22.  
  23. #include <sys/types.h>
  24. #include <sys/stat.h>
  25. #include <string.h>
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <unistd.h>
  29. #include <fcntl.h>
  30. #include <dirent.h>
  31. #include <errno.h>
  32.  
  33. #include <fs_attr.h>
  34. #include <support/TypeConstants.h>
  35. #include <storage/Mime.h>
  36.  
  37. #include "extfs.h"
  38. #include "extfs_defs.h"
  39.  
  40. #define DEBUG 0
  41. #include "debug.h"
  42.  
  43.  
  44. // Default Finder flags
  45. const uint16 DEFAULT_FINDER_FLAGS = kHasBeenInited;
  46.  
  47. // Temporary buffer for transfers from/to kernel space
  48. const int TMP_BUF_SIZE = 0x10000;
  49. static uint8 *tmp_buf = NULL;
  50.  
  51.  
  52. /*
  53.  *  Initialization
  54.  */
  55.  
  56. void extfs_init(void)
  57. {
  58.     // Allocate temporary buffer
  59.     tmp_buf = new uint8[TMP_BUF_SIZE];
  60. }
  61.  
  62.  
  63. /*
  64.  *  Deinitialization
  65.  */
  66.  
  67. void extfs_exit(void)
  68. {
  69.     // Delete temporary buffer
  70.     delete[] tmp_buf;
  71. }
  72.  
  73.  
  74. /*
  75.  *  Add component to path name
  76.  */
  77.  
  78. void add_path_component(char *path, const char *component)
  79. {
  80.     int l = strlen(path);
  81.     if (l < MAX_PATH_LENGTH-1 && path[l-1] != '/') {
  82.         path[l] = '/';
  83.         path[l+1] = 0;
  84.     }
  85.     strncat(path, component, MAX_PATH_LENGTH-1);
  86. }
  87.  
  88.  
  89. /*
  90.  *  Get/set finder info for file/directory specified by full path
  91.  */
  92.  
  93. struct mime2type {
  94.     const char *mime;
  95.     uint32 type;
  96.     uint32 creator;
  97.     bool reversible;    // type -> mime translation possible
  98. };
  99.  
  100. static const mime2type m2t_translation[] = {
  101.     {"application/x-compress", 'ZIVM', 'LZIV', true},
  102.     {"application/x-gzip", 'Gzip', 'Gzip', true},
  103.     {"application/x-macbinary", 'BINA', '????', false},
  104.     {"application/mac-binhex40", 'TEXT', 'SITx', false},
  105.     {"application/pdf", 'PDF ', 'CARO', true},
  106.     {"application/postscript", 'TEXT', 'ttxt', false},
  107.     {"application/x-stuffit", 'SIT!', 'SITx', true},
  108.     {"application/x-tar", 'TARF', 'TAR ', true},
  109.     {"application/x-uuencode", 'TEXT', 'SITx', false},
  110.     {"application/zip", 'ZIP ', 'ZIP ', true},
  111.     {"audio/x-8svx", '8SVX', 'SNDM', true},
  112.     {"audio/x-aifc", 'AIFC', 'TVOD', true},
  113.     {"audio/x-aiff", 'AIFF', 'TVOD', true},
  114.     {"audio/basic", 'ULAW', 'TVOD', true},
  115.     {"audio/x-midi", 'MIDI', 'TVOD', true},
  116.     {"audio/x-mpeg", 'MPG ', 'TVOD', true},
  117.     {"audio/x-wav", 'WAVE', 'TVOD', true},
  118.     {"image/x-bmp", 'BMPf', 'ogle', true},
  119.     {"image/gif", 'GIFf', 'ogle', true},
  120.     {"image/x-ilbm", 'ILBM', 'GKON', true},
  121.     {"image/jpeg", 'JPEG', 'ogle', true},
  122.     {"image/jpeg", 'JFIF', 'ogle', true},
  123.     {"image/x-photoshop", '8BPS', '8BIM', true},
  124.     {"image/pict", 'PICT', 'ogle', true},
  125.     {"image/png", 'PNGf', 'ogle', true},
  126.     {"image/x-sgi", '.SGI', 'ogle', true},
  127.     {"image/x-targa", 'TPIC', 'ogle', true},
  128.     {"image/tiff", 'TIFF', 'ogle', true},
  129.     {"text/html", 'TEXT', 'MOSS', false},
  130.     {"text/plain", 'TEXT', 'ttxt', true},
  131.     {"text/rtf", 'TEXT', 'MSWD', false},
  132.     {"text/x-source-code", 'TEXT', 'R*ch', false},
  133.     {"video/mpeg", 'MPEG', 'TVOD', true},
  134.     {"video/quicktime", 'MooV', 'TVOD', true},
  135.     {"video/x-flc", 'FLI ', 'TVOD', true},
  136.     {"video/x-msvideo", 'VfW ', 'TVOD', true},
  137.     {NULL, 0, 0, false}    // End marker
  138. };
  139.  
  140. void get_finfo(const char *path, uint32 finfo, uint32 fxinfo, bool is_dir)
  141. {
  142.     // Set default finder info
  143.     Mac_memset(finfo, 0, SIZEOF_FInfo);
  144.     if (fxinfo)
  145.         Mac_memset(fxinfo, 0, SIZEOF_FXInfo);
  146.     WriteMacInt16(finfo + fdFlags, DEFAULT_FINDER_FLAGS);
  147.     WriteMacInt32(finfo + fdLocation, (uint32)-1);
  148.  
  149.     // Open file
  150.     int fd = open(path, O_RDONLY);
  151.     if (fd < 0)
  152.         return;
  153.  
  154.     if (!is_dir) {
  155.  
  156.         // Read BeOS MIME type
  157.         ssize_t actual = fs_read_attr(fd, "BEOS:TYPE", B_MIME_STRING_TYPE, 0, tmp_buf, 256);
  158.         tmp_buf[255] = 0;
  159.  
  160.         if (actual > 0) {
  161.  
  162.             // Translate MIME type to MacOS type/creator
  163.             uint8 mactype[4];
  164.             if (sscanf((char *)tmp_buf, "application/x-MacOS-%c%c%c%c", mactype, mactype+1, mactype+2, mactype+3) == 4) {
  165.  
  166.                 // MacOS style type
  167.                 WriteMacInt32(finfo + fdType, (mactype[0] << 24) | (mactype[1] << 16) | (mactype[2] << 8) | mactype[3]);
  168.  
  169.             } else {
  170.  
  171.                 // MIME string, look in table
  172.                 for (int i=0; m2t_translation[i].mime; i++) {
  173.                     if (!strcmp((char *)tmp_buf, m2t_translation[i].mime)) {
  174.                         WriteMacInt32(finfo + fdType, m2t_translation[i].type);
  175.                         WriteMacInt32(finfo + fdCreator, m2t_translation[i].creator);
  176.                         break;
  177.                     }
  178.                 }
  179.             }
  180.         }
  181.  
  182.         // Override file type with MACOS:CREATOR attribute
  183.         if (fs_read_attr(fd, "MACOS:CREATOR", B_UINT32_TYPE, 0, tmp_buf, 4) == 4)
  184.             WriteMacInt32(finfo + fdCreator, (tmp_buf[0] << 24) | (tmp_buf[1] << 16) | (tmp_buf[2] << 8) | tmp_buf[3]);
  185.     }
  186.  
  187.     // Read MACOS:HFS_FLAGS attribute
  188.     if (fs_read_attr(fd, "MACOS:HFS_FLAGS", B_UINT16_TYPE, 0, tmp_buf, 2) == 2)
  189.         WriteMacInt16(finfo + fdFlags, (tmp_buf[0] << 8) | tmp_buf[1]);
  190.  
  191.     // Close file
  192.     close(fd);
  193. }
  194.  
  195. void set_finfo(const char *path, uint32 finfo, uint32 fxinfo, bool is_dir)
  196. {
  197.     // Open file
  198.     int fd = open(path, O_WRONLY);
  199.     if (fd < 0)
  200.         return;
  201.  
  202.     if (!is_dir) {
  203.  
  204.         // Set BEOS:TYPE attribute
  205.         uint32 type = ReadMacInt32(finfo + fdType);
  206.         if (type) {
  207.             for (int i=0; m2t_translation[i].mime; i++) {
  208.                 if (m2t_translation[i].type == type && m2t_translation[i].reversible) {
  209.                     fs_write_attr(fd, "BEOS:TYPE", B_MIME_STRING_TYPE, 0, m2t_translation[i].mime, strlen(m2t_translation[i].mime) + 1);
  210.                     break;
  211.                 }
  212.             }
  213.         }
  214.  
  215.         // Set MACOS:CREATOR attribute
  216.         uint32 creator = ReadMacInt32(finfo + fdCreator);
  217.         if (creator) {
  218.             tmp_buf[0] = creator >> 24;
  219.             tmp_buf[1] = creator >> 16;
  220.             tmp_buf[2] = creator >> 8;
  221.             tmp_buf[3] = creator;
  222.             fs_write_attr(fd, "MACOS:CREATOR", B_UINT32_TYPE, 0, tmp_buf, 4);
  223.         }
  224.     }
  225.  
  226.     // Write MACOS:HFS_FLAGS attribute
  227.     uint16 flags = ReadMacInt16(finfo + fdFlags);
  228.     if (flags != DEFAULT_FINDER_FLAGS) {
  229.         tmp_buf[0] = flags >> 8;
  230.         tmp_buf[1] = flags;
  231.         fs_write_attr(fd, "MACOS:HFS_FLAGS", B_UINT16_TYPE, 0, tmp_buf, 2);
  232.     } else
  233.         fs_remove_attr(fd, "MACOS:HFS_FLAGS");
  234.  
  235.     // Close file
  236.     close(fd);
  237. }
  238.  
  239.  
  240. /*
  241.  *  Resource fork emulation functions
  242.  */
  243.  
  244. uint32 get_rfork_size(const char *path)
  245. {
  246.     // Open file
  247.     int fd = open(path, O_RDONLY);
  248.     if (fd < 0)
  249.         return 0;
  250.  
  251.     // Get size of MACOS:RFORK attribute
  252.     struct attr_info info;
  253.     if (fs_stat_attr(fd, "MACOS:RFORK", &info) < 0)
  254.         info.size = 0;
  255.  
  256.     // Close file and return size
  257.     close(fd);
  258.     return info.size;
  259. }
  260.  
  261. int open_rfork(const char *path, int flag)
  262. {
  263.     // Open original file
  264.     int fd = open(path, flag);
  265.     if (fd < 0)
  266.         return -1;
  267.  
  268.     // Open temporary file for resource fork
  269.     char rname[L_tmpnam];
  270.     tmpnam(rname);
  271.     int rfd = open(rname, O_RDWR | O_CREAT | O_TRUNC, 0666);
  272.     if (rfd < 0) {
  273.         close(fd);
  274.         return -1;
  275.     }
  276.     unlink(rname);    // File will be deleted when closed
  277.  
  278.     // Get size of MACOS:RFORK attribute
  279.     struct attr_info info;
  280.     if (fs_stat_attr(fd, "MACOS:RFORK", &info) < 0)
  281.         info.size = 0;
  282.  
  283.     // Copy resource data from attribute to temporary file
  284.     if (info.size > 0) {
  285.  
  286.         // Allocate buffer
  287.         void *buf = malloc(info.size);
  288.         if (buf == NULL) {
  289.             close(rfd);
  290.             close(fd);
  291.             return -1;
  292.         }
  293.  
  294.         // Copy data
  295.         fs_read_attr(fd, "MACOS:RFORK", B_RAW_TYPE, 0, buf, info.size);
  296.         write(rfd, buf, info.size);
  297.         lseek(rfd, 0, SEEK_SET);
  298.  
  299.         // Free buffer
  300.         if (buf)
  301.             free(buf);
  302.     }
  303.  
  304.     // Close original file
  305.     close(fd);
  306.     return rfd;
  307. }
  308.  
  309. void close_rfork(const char *path, int fd)
  310. {
  311.     if (fd < 0)
  312.         return;
  313.  
  314.     // Get size of temporary file
  315.     struct stat st;
  316.     if (fstat(fd, &st) < 0)
  317.         st.st_size = 0;
  318.  
  319.     // Open original file
  320.     int ofd = open(path, O_WRONLY);
  321.     if (ofd > 0) {
  322.  
  323.         // Copy resource data to MACOS:RFORK attribute
  324.         if (st.st_size > 0) {
  325.  
  326.             // Allocate buffer
  327.             void *buf = malloc(st.st_size);
  328.             if (buf == NULL) {
  329.                 close(ofd);
  330.                 close(fd);
  331.                 return;
  332.             }
  333.  
  334.             // Copy data
  335.             lseek(fd, 0, SEEK_SET);
  336.             read(fd, buf, st.st_size);
  337.             fs_write_attr(ofd, "MACOS:RFORK", B_RAW_TYPE, 0, buf, st.st_size);
  338.  
  339.             // Free buffer
  340.             if (buf)
  341.                 free(buf);
  342.  
  343.         } else
  344.             fs_remove_attr(ofd, "MACOS:RFORK");
  345.  
  346.         // Close original file
  347.         close(ofd);
  348.     }
  349.  
  350.     // Close temporary file
  351.     close(fd);
  352. }
  353.  
  354.  
  355. /*
  356.  *  Read "length" bytes from file to "buffer",
  357.  *  returns number of bytes read (or -1 on error)
  358.  */
  359.  
  360. static inline ssize_t sread(int fd, void *buf, size_t count)
  361. {
  362.     ssize_t res;
  363.     while ((res = read(fd, buf, count)) == B_INTERRUPTED) ;
  364.     return res;
  365. }
  366.  
  367. ssize_t extfs_read(int fd, void *buffer, size_t length)
  368. {
  369.     // Buffer in kernel space?
  370.     if ((uint32)buffer < 0x80000000) {
  371.  
  372.         // Yes, transfer via buffer
  373.         ssize_t actual = 0;
  374.         while (length) {
  375.             size_t transfer_size = (length > TMP_BUF_SIZE) ? TMP_BUF_SIZE : length;
  376.             ssize_t res = sread(fd, tmp_buf, transfer_size);
  377.             if (res < 0)
  378.                 return res;
  379.             memcpy(buffer, tmp_buf, res);
  380.             buffer = (void *)((uint8 *)buffer + res);
  381.             length -= res;
  382.             actual += res;
  383.             if (res != transfer_size)
  384.                 return actual;
  385.         }
  386.         return actual;
  387.  
  388.     } else {
  389.  
  390.         // No, transfer directly
  391.         return sread(fd, buffer, length);
  392.     }
  393. }
  394.  
  395.  
  396. /*
  397.  *  Write "length" bytes from "buffer" to file,
  398.  *  returns number of bytes written (or -1 on error)
  399.  */
  400.  
  401. static inline ssize_t swrite(int fd, void *buf, size_t count)
  402. {
  403.     ssize_t res;
  404.     while ((res = write(fd, buf, count)) == B_INTERRUPTED) ;
  405.     return res;
  406. }
  407.  
  408. ssize_t extfs_write(int fd, void *buffer, size_t length)
  409. {
  410.     // Buffer in kernel space?
  411.     if ((uint32)buffer < 0x80000000) {
  412.  
  413.         // Yes, transfer via buffer
  414.         ssize_t actual = 0;
  415.         while (length) {
  416.             size_t transfer_size = (length > TMP_BUF_SIZE) ? TMP_BUF_SIZE : length;
  417.             memcpy(tmp_buf, buffer, transfer_size);
  418.             ssize_t res = swrite(fd, tmp_buf, transfer_size);
  419.             if (res < 0)
  420.                 return res;
  421.             buffer = (void *)((uint8 *)buffer + res);
  422.             length -= res;
  423.             actual += res;
  424.             if (res != transfer_size)
  425.                 return actual;
  426.         }
  427.         return actual;
  428.  
  429.     } else {
  430.  
  431.         // No, transfer directly
  432.         return swrite(fd, buffer, length);
  433.     }
  434. }
  435.  
  436.  
  437. /*
  438.  *  Remove file/directory, returns false on error (and sets errno)
  439.  */
  440.  
  441. bool extfs_remove(const char *path)
  442. {
  443.     if (remove(path) < 0) {
  444.         if (errno == EISDIR)
  445.             return rmdir(path) == 0;
  446.         else
  447.             return false;
  448.     }
  449.     return true;
  450. }
  451.  
  452.  
  453. /*
  454.  *  Rename/move file/directory, returns false on error (and sets errno)
  455.  */
  456.  
  457. bool extfs_rename(const char *old_path, const char *new_path)
  458. {
  459.     return rename(old_path, new_path) == 0;
  460. }
  461.